package com.vast.ui.component.socketinterface.server;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.net.Socket;

import com.vast.ui.component.socketinterface.protocol.VaSTUIComponentProtocol;
import com.vast.ui.component.socketinterface.request.Request;
import com.vast.ui.component.socketinterface.request.RequestQueue;
import com.vast.ui.component.state.Sequence;
import com.vast.ui.component.util.ConsoleLoggerSingleton;
import com.vast.ui.component.util.Logger;
import com.vast.ui.panel.led.Activator;
import com.vast.ui.panel.led.preferences.PreferenceConstants;

public class ReceiveHandler implements Runnable {
    private Socket             clientRecvSocket;
    private DataInputStream    in;
    private DecodeRequester    decodeRequester;
    private int                receiveWait;
	private final Sequence     sequence;
	private final RequestQueue receivedQueue;
	private final Logger       logger;
	
    ReceiveHandler(Socket clientRecvSocket, Sequence sequence, RequestQueue  receivedQueue, DecodeRequester decodeRequester) {
        this.clientRecvSocket = clientRecvSocket;
        this.decodeRequester  = decodeRequester;
        this.sequence      = sequence;
        this.receivedQueue = receivedQueue;
        this.receiveWait   = Activator.getDefault().getPreferenceStore().getInt(PreferenceConstants.P_WAIT_VALUE);
        this.logger        = ConsoleLoggerSingleton.getInstance();
    }
    
    public void run() {
        try {
        	in = new DataInputStream(new BufferedInputStream(clientRecvSocket.getInputStream()));

        	int ch1 = 0;
        	int ch2 = 0;
        	int ch3 = 0;
        	int ch4 = 0;
        	int sizeOfData = 0;
        	int command    = 0;

        	while(sequence.isReceiveConnection()) {
        		int endMarker  = 0;
        		
        		ch1 = 0xFF & in.readByte();
        		ch2 = 0xFF & in.readByte();
        		ch3 = 0xFF & in.readByte();
        		ch4 = 0xFF & in.readByte();
        		sizeOfData =  ((ch1 << 24)) | ((ch2 << 16)) | ((ch3 << 8)) | (ch4);
                	
        		ch1 = 0xFF & in.readByte();
        		ch2 = 0xFF & in.readByte();
        		ch3 = 0xFF & in.readByte();
        		ch4 = 0xFF & in.readByte();
        		command = ((ch1 << 24)) | ((ch2 << 16)) | ((ch3 << 8)) | (ch4);

        		Request request = null;
                	
        		request = new Request(sizeOfData - 8);
                	
        		request.command = command;
        		if (request.command == VaSTUIComponentProtocol.PK_SOCKET_TERMINATE) {
        			decodeRequester.decodeRequest(request);
        			in.read(request.data, 0, request.data.length);
        			ch1 = 0xFF & request.data[request.data.length - 4];
            		ch2 = 0xFF & request.data[request.data.length - 3];
            		ch3 = 0xFF & request.data[request.data.length - 2];
            		ch4 = 0xFF & request.data[request.data.length - 1];
            		endMarker = ((ch1 << 24)) | ((ch2 << 16)) | ((ch3 << 8)) | (ch4);
        			return;
        		}

        		in.read(request.data, 0, request.data.length);
                	
        		ch1 = 0xFF & request.data[request.data.length - 4];
        		ch2 = 0xFF & request.data[request.data.length - 3];
        		ch3 = 0xFF & request.data[request.data.length - 2];
        		ch4 = 0xFF & request.data[request.data.length - 1];
        		endMarker = ((ch1 << 24)) | ((ch2 << 16)) | ((ch3 << 8)) | (ch4);  
                    
        		while(endMarker != VaSTUIComponentProtocol.PK_END_MARKER){
        			ch1 = 0xFF & request.data[request.data.length - 4];
            		ch2 = 0xFF & request.data[request.data.length - 3];
            		ch3 = 0xFF & request.data[request.data.length - 2];
            		ch4 = 0xFF & request.data[request.data.length - 1];
            		endMarker = ((ch1 << 24)) | ((ch2 << 16)) | ((ch3 << 8)) | (ch4);
                    //logger.writeEntry(Activator.PLUGIN_ID + ": EndMarker is reloaded : 0x" + Integer.toHexString(endMarker));
        		}
        		
        		if(endMarker != VaSTUIComponentProtocol.PK_END_MARKER) {
        			logger.writeEntry(Activator.PLUGIN_ID + ": EndMarker is broken : 0x" + Integer.toHexString(endMarker));
                	logger.writeEntry(Activator.PLUGIN_ID + ": request.command : 0x" + Integer.toHexString(request.command));
                	logger.writeEntry(Activator.PLUGIN_ID + ": deta size : 0x" +  Integer.toHexString(sizeOfData));
                	logger.writeEntry(Activator.PLUGIN_ID + ": request.data.length :" + request.data.length);
                	for(int j = 0; j < request.data.length; j++) {
                		logger.writeEntry(Activator.PLUGIN_ID + ": request.data[" + j + "] : 0x" + Integer.toHexString(request.data[j]));
                	}
                	request.command = VaSTUIComponentProtocol.PK_SOCKET_TERMINATE;
                }
                decodeRequester.decodeRequest(request);
                if(receiveWait != 0) {
                	Thread.sleep(receiveWait);
                }
                //receivedQueue.putRequest(request);
        	}
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {           	
            	while(in.available() > 0) {
            		logger.writeEntry(Activator.PLUGIN_ID + ": Avalirable :" + in.available());
            		byte b[] = new byte[in.available()];	
            		in.readFully(b);
            		logger.writeEntry(Activator.PLUGIN_ID + ": Avalirable after readFully() :" + in.available());
            	}
            	
                in.close();
                clientRecvSocket.close();
                logger.writeEntry(Activator.PLUGIN_ID + ": Exit Receive Handler.");
            } catch (Exception e) {}
        }
    }
}
